package com.jingdun.sport.rp

import cn.hutool.core.util.RandomUtil
import com.aliyuncs.DefaultAcsClient
import com.aliyuncs.IAcsClient
import com.aliyuncs.cloudauth.model.v20190307.*
import com.aliyuncs.exceptions.ClientException
import com.aliyuncs.http.ProtocolType
import com.aliyuncs.profile.DefaultProfile
import com.jingdun.sport.authority.Users
import com.jingdun.sport.common.bean.ALiDaYu
import com.jingdun.sport.common.constants.RedisConstants
import com.jingdun.sport.common.util.RedisUtil
import com.jingdun.sport.data.environment.DataEnvironment
import com.jingdun.sport.security.util.SecurityUtils
import com.losttemple.sql.language.operator.db
import com.losttemple.sql.language.operator.eq
import io.swagger.annotations.ApiOperation
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

data class RPResult(
        val sex: String,
        val name: String,
        val birth: String,
        val user: String
)

interface RPCallback {
    fun succeed(result: RPResult)
    fun failed(user: String)
}

@RestController
@RequestMapping("/sport/rp/")
class RPController(private val callbacks: List<RPCallback>) {
    private val logger: Logger = LoggerFactory.getLogger(RPController::class.java)

    @Autowired
    private var aLiDaYu: ALiDaYu? = null

    @Autowired
    private lateinit var sql: DataEnvironment

    private fun succeedCallback(result: RPResult) {
        for (callback in callbacks) {
            callback.succeed(result)
        }
    }

    @GetMapping("/test")
    fun testRP(): ResponseEntity<String> {
        val userId: String = SecurityUtils.getUser().userId
        succeedCallback(RPResult("mail", "330802198306282547", "1983/6/28", userId))
        return ResponseEntity.ok("1")
    }

    @GetMapping("/h5_check_face")
    @ApiOperation(value = "", notes = "h5实人认证接口")
    fun getUserCheck(photoUrl: String, name: String?, idNumber: String?): ResponseEntity<String> {
        val userId: String = SecurityUtils.getUser().userId
        val bizId: String = RedisUtil.get(RedisConstants.RPBizId + userId)
                ?: return ResponseEntity.ok("未开始实人认证")
        val profile = DefaultProfile.getProfile(
                "cn-hangzhou",  // 固定cn-hangzhou
                aLiDaYu?.accessKeyId,  // 您的Access Key ID
                aLiDaYu?.accessKeySecret) // 您的Access Key Secret
        val client: IAcsClient = DefaultAcsClient(profile)

//若接入方的人脸图片是本地资源，则可以使用实人认证提供的上传SDK将图片直传到实人认证OSS Bucket并获取到图片地址。如果您的业务需要使用上传SDK，请提交工单联系我们获取。

//接入方服务端提交认证，接口文档：https://help.aliyun.com/document_detail/154607.html
        val request = VerifyMaterialRequest()
        //具体传参
        request.regionId = "cn-hangzhou"
        //        request.setSysProtocol(ProtocolType.HTTPS);
        request.bizId = bizId
        request.bizType = "h5-checkface" //创建方法请参见https://help.aliyun.com/document_detail/127885.html
        request.name = name
        request.idCardNumber = idNumber
        request.faceImageUrl = photoUrl // faceImageUrl可以是通过直传OSS获取到的链接，也可以是接入方公网可访问的人脸图片链接，支持http/https
        var retry = 5
        var verifyMaterialResponse: VerifyMaterialResponse? = null
        while (retry > 0) {
            try {
                verifyMaterialResponse = client.getAcsResponse(request)
            } catch (ce: ClientException) {
                retry--
            }
        }
        if (verifyMaterialResponse == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
        }
        val statusCode: Int = verifyMaterialResponse.verifyStatus //同步返回认证状态和相应材料
        if (statusCode == 1) {
            val material = verifyMaterialResponse.material
            val idCardInfo = material.idCardInfo
            succeedCallback(RPResult(idCardInfo.sex, idCardInfo.name, idCardInfo.birth, userId))
            sql.run {
                db { Users(it) }
                        .where { id eq userId }
                        .update {
                            it.realName(idCardInfo.name)
                            it.sex(idCardInfo.sex)
                            it.birthDate(idCardInfo.birth)
                        }()
            }
            RedisUtil.del(RedisConstants.RPBizId + userId)
        }
        return ResponseEntity.ok(statusCode.toString())
    }

    @GetMapping("/realyPersonToken")
    @ApiOperation(value = "获取实人认证所需的token", notes = "获取实人认证所需的token")
    fun realyPersonToken(@RequestParam(defaultValue = "0") type: Int): ResponseEntity<String> {
        val userId = SecurityUtils.getUser().userId
        return if (RedisUtil.get<String>(RedisConstants.RPSign + userId) == null) {
            val profile = DefaultProfile.getProfile(
                    "cn-hangzhou",  // 固定cn-hangzhou
                    aLiDaYu!!.accessKeyId,  // 您的Access Key ID
                    aLiDaYu!!.accessKeySecret) // 您的Access Key Secret
            val client: IAcsClient = DefaultAcsClient(profile)

//1. 接入方服务端发起认证请求，获得认证token，接口文档：https://help.aliyun.com/document_detail/154605.html
            val request = DescribeVerifyTokenRequest()
            //具体传参
            request.sysRegionId = "cn-hangzhou"
            request.sysProtocol = ProtocolType.HTTPS
            val bizId = RandomUtil.randomNumbers(13)
            RedisUtil.set(RedisConstants.RPBizId + userId, bizId, RedisConstants.RPTimeOut)
            request.bizId = bizId
            if (type == 0) {
                request.bizType = "sports"
            } else {
                request.bizType = "h5-checkface"
            }
            //创建方法请参见https://help.aliyun.com/document_detail/127885.html
            var response: DescribeVerifyTokenResponse? = null
            try {
                response = client.getAcsResponse(request)
            } catch (e: ClientException) {
                e.printStackTrace()
                return ResponseEntity.ok("调用阿里云实人认证失败")
            }
            val verifyToken = response.verifyToken
            ResponseEntity.ok(verifyToken)
        } else {
            ResponseEntity.ok("用户已经在实人认证过程中")
        }
    }

    @GetMapping("/checkRealyPersonResult")
    @ApiOperation(value = "判断实人认证状态", notes = "判断实人认证状态")
    fun checkRealyPersonResult(): ResponseEntity<String> {
        val userId = SecurityUtils.getUser().userId
        val bizId: String? = RedisUtil.get(RedisConstants.RPBizId + userId)
        if (bizId != null) {
            val profile = DefaultProfile.getProfile(
                    "cn-hangzhou",  // 固定cn-hangzhou
                    aLiDaYu!!.accessKeyId,  // 您的Access Key ID
                    aLiDaYu!!.accessKeySecret) // 您的Access Key Secret
            val client: IAcsClient = DefaultAcsClient(profile)
            val verifyResultRequest = DescribeVerifyResultRequest()
            //具体传参
            verifyResultRequest.regionId = "cn-hangzhou"
            verifyResultRequest.sysProtocol = ProtocolType.HTTPS
            verifyResultRequest.bizId = bizId
//            verifyResultRequest.bizType = "h5-checkface"
            verifyResultRequest.bizType = "sports"
            val verifyResultResponse: DescribeVerifyResultResponse
            verifyResultResponse = try {
                client.getAcsResponse(verifyResultRequest)
            } catch (e: ClientException) {
                e.printStackTrace()
                return ResponseEntity.ok("调用阿里云实人认证失败")
            }
            return if (verifyResultResponse.verifyStatus == 1) {
                val material = verifyResultResponse.material
                val idCardInfo = material.idCardInfo
                succeedCallback(RPResult(idCardInfo.sex, idCardInfo.name, idCardInfo.birth, userId))
                sql.run {
//                    db { Users(it) }
//                            .where { id eq result.user }
//                            .update {
//                                it.authentic(true)
//                            }()
                }
                RedisUtil.del(RedisConstants.RPBizId + userId)
                ResponseEntity.ok("1")
            } else {
                ResponseEntity.ok("verify failed: ${verifyResultResponse.verifyStatus}")
            }
        } else {
            return ResponseEntity.ok("bizId not exist")
        }
    }
}